package com.innovation.dao;

import java.net.UnknownHostException;

import org.apache.log4j.Logger;

import com.google.code.morphia.Datastore;
import com.google.code.morphia.Morphia;
import com.google.code.morphia.logging.MorphiaLoggerFactory;
import com.google.code.morphia.logging.slf4j.SLF4JLogrImplFactory;
import com.innovation.config.GlobalConfig.MongoConfig;
import com.innovation.data.model.BaseModel;
import com.innovation.exception.DBException;
import com.innovation.server.GameServer;
import com.mongodb.DBAddress;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.MongoOptions;

public abstract class BaseDao<T extends BaseModel> {
	
	private static final Logger log = Logger.getLogger(BaseDao.class);
	private static Mongo mongo = null;
	private static Morphia morphia = null;
	
	/**
	 * 初始化Mongo实例
	 * 
	 * @throws Exception
	 */
	public static void initMongo() throws Exception {
		MongoConfig config = GameServer.ZONE.mongoConfig;
		mongo = createMongo(config.host, config.port, config.dbName);
		if( mongo == null ) {
			throw new Exception("init mongo db exception, dbName="+config.dbName);
		}
		
		MorphiaLoggerFactory.registerLogger(SLF4JLogrImplFactory.class);
		morphia = new Morphia();
		
	}
	
	/**
	 * 创建Mongo实例
	 * 
	 * @param host
	 * @param port
	 * @param dbName
	 * @return
	 */
	private static Mongo createMongo(String host, int port, String dbName) {
		try {
			MongoOptions options = new MongoOptions();
			options.autoConnectRetry = true;
			// options.threadsAllowedToBlockForConnectionMultiplier = 3;
			// options.connectionsPerHost = 2;
			Mongo mongo = new Mongo(new DBAddress(host, port, dbName), options);
			log.debug("new mongo:{" + mongo.hashCode() + "}|{" + mongo.debugString() + "}");
			return mongo;
		} catch (UnknownHostException ex) {
			log.error("UnknownHostException:" + ex.getMessage());
		} catch (MongoException ex) {
			log.error("Mongo Exception:", ex);
		}
		return null;
	}
	
	/**
	 * 获取数据源
	 * @return
	 */
	public Datastore getDatastore() {
		//TODO datasource不能缓存?
		return morphia.createDatastore(mongo, GameServer.ZONE.mongoConfig.dbName);
	}
	
//	/**
//	 * 更新数据操作
//	 * 
//	 * @param model
//	 * @return
//	 */
//	public UpdateOperations<T> getUpdateOperations(Class<T> clazz) {
//		return getDatastore().createUpdateOperations(clazz);
//	}

//	/**
//	 * 获取查询对象
//	 * 
//	 * @param model
//	 * @param clazz
//	 * @return
//	 */
//	public Query<T> getQuery(Class<T> clazz) {
//		return getDatastore().createQuery(clazz);
//	}

	/**
	 * 保存
	 * 
	 * @param model
	 */
	public void save(T model) {
		final Datastore ds = getDatastore();
		try {
			ds.save(model);
		} catch (Exception e) {
			log.error(e.getMessage());
			throw new DBException(e);
		}
	}

//	/**
//	 * 更新
//	 * 
//	 * @param model
//	 * @param query
//	 * @param ops
//	 */
//	public void update(Query<T> query, UpdateOperations<T> ops) {
//		final Datastore ds = getDatastore();
//		try {
//			ds.update(query, ops);
//		} catch (Exception e) {
//			log.error(e.getMessage());
//		}
//	}	
	
//	/**
//	 * 删除
//	 * 
//	 * @param object
//	 */
//	public void delete(Query<T> query) {
//		final Datastore ds = getDatastore();
//		try {
//			ds.delete(query);
//		} catch (Exception e) {
//			log.error(e.getMessage());
//		}
//	}
	
//	/**
//	 * 插入操作
//	 * @param model
//	 * @throws DBException
//	 */
//	public abstract void insert(T model) throws DBException;
//	
//	/**
//	 * 更新操作
//	 * @param model
//	 * @throws DBException
//	 */
//	public abstract void update(T model) throws DBException;
//	
//	/**
//	 * 删除操作
//	 * @param model
//	 * @throws DBException
//	 */
//	public abstract void delete(T model) throws DBException;
}
